package intersectionSegment;

import java.util.*;
import base.*;

public class LigneFlottante {
	TreeSet<SegmentFlottant> tree = new TreeSet<SegmentFlottant>();
	Point p;

	
	
	@Override
	public String toString() {
		StringBuffer res = new StringBuffer("{ ");
		for (SegmentFlottant s:tree)
			res.append(s.toString()+ " ");
			res.append("}");
		return "LigneFlottante [tree=" + res.toString() + ", p=" + p + "]";
	}

	public class SegmentFlottant implements Comparable<SegmentFlottant> {
		Segment segment;

		SegmentFlottant(Segment s) {
			this.segment = s;
		}
		
		@Override
		public String toString() {
			return "SegmentFlottant [segment=" + segment + "]";
		}


		public int compareTo(SegmentFlottant s) {
			return -biscompareTo(s);
		}
		private int biscompareTo(SegmentFlottant s) {
			if (this.segment.debut.y == this.segment.fin.y) {
				if (s.segment.debut.y == s.segment.fin.y) {
					if (s.segment.fin.x > this.segment.fin.x)
						return 1;
					else if (s.segment.fin.x < this.segment.fin.x)
						return -1;
					else
						return 0;
				}
				else {
					Point sp = s.segment.intersectionHorizontale(p.y);
					if (sp.equals(p)) {
						return (this.segment.debut.x<this.segment.fin.x)?-1:1;
					}
						else
						return (sp.x<p.x)?-1:1;
				}
			}
			else if (s.segment.debut.y == s.segment.fin.y) {
				Point segmentp = this.segment.intersectionHorizontale(p.y);
				if (segmentp.equals(p))
					return (s.segment.debut.x<s.segment.fin.x)?1:-1;
				else
					return (segmentp.x<p.x)?1:-1;
			}

			Point segmentp = this.segment.intersectionHorizontale(p.y);
			Point sp = s.segment.intersectionHorizontale(p.y);

			if (sp.x < segmentp.x)
				return -1;
			else if (sp.x > segmentp.x)
				return 1;
			else {
				float produit = segment.produitVectoriel(s.segment);
				if (produit > 0)
					return 1;
				else if (produit < 0)
					return -1;
				else if (s.segment.fin.x > segment.fin.x)
					return 1;
				else if (s.segment.fin.x < segment.fin.x)
					return -1;
				else
					return s.segment.superHashCode() - segment.superHashCode();
			}
		}
	}

	public void remove(Segment s) {
		tree.remove(new SegmentFlottant(s));
	}

	public void add(Segment s) {
		tree.add(new SegmentFlottant(s));
	}

	public Segment lower() {
		if (tree.size() == 0)
			return null;
		SegmentFlottant s = tree.first();
		if (s.segment.debut.equals(p))
			return null;

		Point ps = s.segment.intersectionHorizontale(p.y);
		if (ps.equals(p))
			return null;
		
		s = new SegmentFlottant(new Segment(p, new Point(-Float.MAX_VALUE, p.y)));		
		return tree.lower(s).segment;
	}

	public Segment higher() {
		if (tree.size() == 0)
			return null;
		SegmentFlottant s = tree.last();
		if (s.segment.debut.equals(p))
			return null;

		Point ps = s.segment.intersectionHorizontale(p.y);
		if (ps.equals(p))
			return null;
		
		s = new SegmentFlottant(new Segment(p, new Point(Float.MAX_VALUE, p.y)));
		return tree.higher(s).segment;
	}

	public Segment floor() {
		SegmentFlottant s = new SegmentFlottant(new Segment(p, new Point(Float.MAX_VALUE, p.y)));
		tree.add(s);
		Segment res = tree.lower(s).segment;
		tree.remove(s);
		return res;

		//		return tree.floor(s).segment;
	}

	public Segment ceiling() {
		SegmentFlottant s = new SegmentFlottant(new Segment(p, new Point(-Float.MAX_VALUE, p.y)));
		tree.add(s);
		Segment res = tree.higher(s).segment;
		tree.remove(s);
		return res;
//		return tree.ceiling(s).segment; probleme avec ceilling !
	}

}
